package com.strongbj.iot.devices.amazondb.response.coder;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;

import com.strongbj.core.util.Aes;
import com.strongbj.iot.devices.amazonreader.message.ReaderMessage;
/**
 * 通过5A A5解决粘包问题，再转换为可用ReaderMessage信息
 * 通过5A A5协议头拆包，会出现最后一条收不到的问题。
 * @author yuzhantao
 *
 */
public class ReaderDecoder  extends DelimiterBasedFrameDecoder {
	private final static String BODY_KEY = "1234567890123456"; // 数据区秘钥
	
	private static final int RESERVATIONS_SIZE = 15; //数据保留区长度
	
	private static final int RCR_SIZE = 2;			// 效验码的长度
	// 头部起始码 0x5a 0xa5
	private static final int HEADER_SIZE = 8;		// 数据头的长度
	
	private static final int VALID_LENGHT=HEADER_SIZE+RESERVATIONS_SIZE+RCR_SIZE; // 有效长度

	// 地址码
	private byte[] address = new byte[3];

	// 类型码
	private byte type;

	// 数据长度
	@SuppressWarnings("unused")
	private short length;
	
	@SuppressWarnings("unused")
	private byte tFrame;
	
	@SuppressWarnings("unused")
	private byte cFrame;
	
	// 保留区
	private byte[] reservations=new byte[15];
	// 正文
	private byte[] body=new byte[1];

	public ReaderDecoder(int maxFrameLength) {
		super(maxFrameLength, Unpooled.copiedBuffer(
				new byte[]{0x5a,Integer.valueOf("A5", 16).byteValue()})); // 通过5A A5解决粘包问题
	}
	
	@Override  
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { 
    	in = (ByteBuf) super.decode(ctx, in);  // 通过A5 5A协议头来拆包
    	
    	if(in==null || in.readableBytes()==0){
    		return in;
    	}

    	// 可读信息段比头部信息小
        if (in.readableBytes() < VALID_LENGHT) {  
            return null;
        }
        in.readBytes(address);
        type = in.readByte();
        length = in.readShort();
        tFrame = in.readByte();
        cFrame = in.readByte();
        in.readBytes(reservations);
        
        // 读取有效加密数据
        byte[] encryptionBody = new byte[in.readableBytes()-RCR_SIZE];
        in.readBytes(encryptionBody);
        body = Aes.Decrypt(encryptionBody, BODY_KEY); 
        
        in.release();
        
        ReaderMessage message = new ReaderMessage(address,type,body);
        return message;
    }
}
